package com.app.android.coliy.manager;

import android.graphics.Bitmap;
import android.graphics.Color;
//import android.support.annotation.RequiresApi;

import static java.lang.Math.ceil;

import java.util.Random;

import com.app.android.coliy.bean.PrintSettingInfo;
import com.app.android.coliy.util.BitmapUtil;
import com.app.android.coliy.util.PackBits;

import java.io.IOException;

public class BuildPackgeManager {

    byte[] imageData_first;
    byte[] imageData_copy;

    Bitmap bitmap_first;
    Bitmap bitmap_copy;   //镜像后的图片

    int cCount = 0;
    int mCount = 0;
    int yCount = 0;
    int cBCount = 0;
    int mBCount = 0;
    int yBCount = 0;

    boolean isOld = false;

    /**
     * BuildPackgeManager 实例化
     * @param baseBitmap 图片源数据
     * @param hasImage   是否包含图片元素
     * @param isOld      是否是老机器
     */
    public BuildPackgeManager(Bitmap baseBitmap, boolean hasImage, boolean isOld) {
        this.bitmap_first = baseBitmap;
        this.bitmap_copy = BitmapUtil.convertBitmap(baseBitmap);
        this.isOld = isOld;

        //这里根据蓝牙设备名PKK10000000,之前的按照以前的单文件数据格式，第二个参数为false;
        //PKK10000000之后的采用群文件的格式发送，需要发送一次握手协议告知设备当前发送的文件个数;
        //第三个参数需要检测打印模板是否包含图片文件，如果有，则true；反之，则false;
        if (isOld) {
            //老版本机器
            imageData_first = new DataFamet(bitmap_first).getImageData(true, false, hasImage);
            imageData_copy = new DataFamet(bitmap_copy).getImageData(false, false, hasImage);
        } else {
            imageData_first = new DataFamet(bitmap_first).getImageData(true, true, hasImage);
        }
    }

    //生成多文件握手包
    public static byte[] buildPacket_mutiFile(int count) {
        byte[] bytes = new byte[20 + 24];   // 发送数据总长度为header 12字节 + png数据长度
        //头部数据
        byte[] head0 = {(byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80};    //固定值
        byte[] head1 = intToByte(0);                             //第1张图数据数组长度
        byte[] head4 = intToByte(0);                                //第2张图数据数组长度
        byte[] head2 = intToByte(0x89);                                     //cmd固定值
        byte[] head3 = intToByte(count);                        //图片列数 ,加10为实际打印列数偏移量,24是CMY混色偏移
        byte[] head_cmy = new byte[24];
        for (int i = 0; i < 24; i++) {
            head_cmy[i] = 0;
        }

        //组包  头部
        System.arraycopy(head0, 0, bytes, 0, 4);
        System.arraycopy(head1, 0, bytes, 4, 4);
        System.arraycopy(head4, 0, bytes, 8, 4);
        System.arraycopy(head2, 0, bytes, 12, 4);
        System.arraycopy(head3, 0, bytes, 16, 4);
        System.arraycopy(head_cmy, 0, bytes, 20, 24);
        return bytes;    // 返回的就是组好包的 byte [], 通过FscBleCentralApi的send接口发送出去
    }

    //生成打印设置
    public static byte[] buildPacket_printsetting(PrintSettingInfo printSettingInfo) {
        byte[] bytes = new byte[20 + 24];   // 发送数据总长度为header 12字节 + png数据长度
        //头部数据
        byte[] head0 = {(byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80};    //固定值
        byte[] head1 = intToByte(0);
        byte[] head4 = intToByte(0);
        byte[] head2 = intToByte(0x8a);                                     //cmd固定值
        byte[] head3 = intToByte(printSettingInfo.type);                            //打印模式
        byte[] head5 = intToByte(printSettingInfo.trigger_mode);                    //触发方式
        byte[] head6 = intToByte(printSettingInfo.message_delay);                   //消息延时
        byte[] head7 = intToByte(printSettingInfo.printing_precision);              //喷印精度
        byte[] head8 = intToByte(0);
        byte[] head9 = intToByte(0);
        byte[] head10 = intToByte(0);

        //组包  头部
        System.arraycopy(head0, 0, bytes, 0, 4);
        System.arraycopy(head1, 0, bytes, 4, 4);
        System.arraycopy(head4, 0, bytes, 8, 4);
        System.arraycopy(head2, 0, bytes, 12, 4);
        System.arraycopy(head3, 0, bytes, 16, 4);
        System.arraycopy(head5, 0, bytes, 20, 4);
        System.arraycopy(head6, 0, bytes, 24, 4);
        System.arraycopy(head7, 0, bytes, 28, 4);
        System.arraycopy(head8, 0, bytes, 32, 4);
        System.arraycopy(head9, 0, bytes, 36, 4);
        System.arraycopy(head10, 0, bytes, 40, 4);
        return bytes;    // 返回的就是组好包的 byte [], 通过FscBleCentralApi的send接口发送出去
    }


    //生成第一次握手包
    public byte[] buildPacket_First() {
        byte[] bytes = new byte[20 + 24];   // 发送数据总长度为header 12字节 + png数据长度
        //图片长度
        int copey_length = 0;
        int head3_length=0;
        if (isOld) {
            copey_length = imageData_copy.length;
            head3_length = bitmap_first.getHeight() ;
        } else {
            copey_length = 0;
            head3_length = bitmap_first.getHeight() + 10 + 24 * 2;
        }
        //头部数据
        byte[] head0 = {(byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80};   //固定值
        byte[] head1 = intToByte(imageData_first.length);                      //第1张图数据数组长度
        byte[] head4 = intToByte(copey_length);                                        //第2张图数据数组长度
        byte[] head2 = intToByte(0x88);                                     //固定值
        byte[] head3 = intToByte(head3_length);         //图片列数 ,加10为实际打印列数偏移量,24是CMY混色偏移
        byte[] head5 = intToByte(cBCount);
        byte[] head6 = intToByte(mBCount);
        byte[] head7 = intToByte(yBCount);
        byte[] head8 = intToByte(cCount);
        byte[] head9 = intToByte(mCount);
        byte[] head10 = intToByte(yCount);

        //组包  头部
        System.arraycopy(head0, 0, bytes, 0, 4);
        System.arraycopy(head1, 0, bytes, 4, 4);
        System.arraycopy(head4, 0, bytes, 8, 4);
        System.arraycopy(head2, 0, bytes, 12, 4);
        System.arraycopy(head3, 0, bytes, 16, 4);
        System.arraycopy(head5, 0, bytes, 20, 4);
        System.arraycopy(head6, 0, bytes, 24, 4);
        System.arraycopy(head7, 0, bytes, 28, 4);
        System.arraycopy(head8, 0, bytes, 32, 4);
        System.arraycopy(head9, 0, bytes, 36, 4);
        System.arraycopy(head10, 0, bytes, 40, 4);

        return bytes;    // 返回的就是组好包的 byte [], 通过FscBleCentralApi的send接口发送出去
    }

    //生成第二次数据包
    public byte[] buildPacket_sencond() {
        byte[] bytes = null;
        if (isOld) {
            bytes = new byte[imageData_first.length + imageData_copy.length];
            System.arraycopy(imageData_first, 0, bytes, 0, imageData_first.length);
            System.arraycopy(imageData_copy, 0, bytes, imageData_first.length, imageData_copy.length);
        } else {
            bytes = new byte[imageData_first.length];
            System.arraycopy(imageData_first, 0, bytes, 0, imageData_first.length);
        }
        return bytes;    // 返回的就是组好包的 byte [], 通过FscBleCentralApi的send接口发送出去
    }

    private static byte[] intToByte(int i) {
        byte[] result = new byte[4];
        // 由高位到低位
        result[0] = (byte) ((i >> 24) & 0xFF);
        result[1] = (byte) ((i >> 16) & 0xFF);
        result[2] = (byte) ((i >> 8) & 0xFF);
        result[3] = (byte) (i & 0xFF);
        return result;
    }

    private class DataFamet {
        int[] cByte;
        int[] mByte;
        int[] yByte;
        byte[] bytesArr_sum;
        byte[] imageData;

        int[] cByte_tmp;
        int[] mByte_tmp;
        int[] yByte_tmp;

        int[] cByte_HT;
        int[] mByte_HT;
        int[] yByte_HT;

        Bitmap bitmap;
        int imgWidth = 0;
        int imgHeight = 0;
        int arrLength = 0;

        int imgLength = 0;

        int lo_hi_offset = 10;  //10
        int offset_bytes = 0;

        int cmy_offset = 24;    //24
        int m_offset_bytes = 0;
        int y_offset_bytes = 0;

        public DataFamet(Bitmap baseBitmap) {
            this.bitmap = baseBitmap;

            imgWidth = bitmap.getWidth();
            imgHeight = bitmap.getHeight();

            arrLength = imgWidth * (imgHeight + lo_hi_offset + cmy_offset * 2) * 2;

            offset_bytes = lo_hi_offset * imgWidth * 2;
            m_offset_bytes = cmy_offset * imgWidth * 2;
            y_offset_bytes = cmy_offset * 2 * imgWidth * 2;

            cByte = new int[arrLength];
            mByte = new int[arrLength];
            yByte = new int[arrLength];

            imgLength = imgWidth * imgHeight;

            cByte_tmp = new int[imgLength];
            mByte_tmp = new int[imgLength];
            yByte_tmp = new int[imgLength];

            cByte_HT = new int[imgLength];
            mByte_HT = new int[imgLength];
            yByte_HT = new int[imgLength];
        }

        public byte[] getImageData(boolean isForwardDir, boolean isNewFormat, boolean isAddImagePreprocess) {
            ink_seperation_colormap(cByte_tmp, mByte_tmp, yByte_tmp, imgWidth, imgHeight, isAddImagePreprocess);
            if (isAddImagePreprocess) {
                floyd_steinberg_mbpp(cByte_tmp, imgWidth, imgHeight, cByte_HT);
                floyd_steinberg_mbpp(mByte_tmp, imgWidth, imgHeight, mByte_HT);
                floyd_steinberg_mbpp(yByte_tmp, imgWidth, imgHeight, yByte_HT);
            } else {
                System.arraycopy(cByte_tmp, 0, cByte_HT, 0, imgLength);
                System.arraycopy(mByte_tmp, 0, mByte_HT, 0, imgLength);
                System.arraycopy(yByte_tmp, 0, yByte_HT, 0, imgLength);
            }
            extractPixelData(isForwardDir, isNewFormat);
            mergeCMYData();
            packbitsEncode();
            return imageData;
        }

        // [4] 提取像素数据, RGB转CMY并分别填充到cBits, mBits, yBits
        private void extractPixelData(boolean isForwardDir, boolean isNewFormat) {
            int cnt = 0;
            int nozzleNum = 0;

            cCount = 0;
            mCount = 0;
            yCount = 0;
            cBCount = 0;
            mBCount = 0;
            yBCount = 0;

            //以前的数据格式，在app上打印数据不需要偏移，拼接由fpga去完成
            if (isNewFormat == false) {
                offset_bytes = 0;
                m_offset_bytes = 0;
                y_offset_bytes = 0;
            }

            for (int i = 0; i < imgLength; i++) {
                if ((cnt % 2) == 1) {
                    if ((cByte_HT[i] & 0x80) == 0x80) {
                        nozzleNum = cnt * 2 + 1;
                        cBCount += 1;
                        if (isForwardDir) {
                            cByte[nozzleNum] = 1;
                        } else {
                            cByte[nozzleNum + offset_bytes + y_offset_bytes] = 1;
                        }
                    }
                    if ((cByte_HT[i] & 0x40) == 0x40) {
                        nozzleNum = cnt * 2;
                        cCount += 1;
                        if (isForwardDir) {
                            cByte[nozzleNum + offset_bytes] = 1;
                        } else {
                            cByte[nozzleNum + y_offset_bytes] = 1;
                        }
                    }
                    if ((mByte_HT[i] & 0x80) == 0x80) {
                        nozzleNum = cnt * 2 + 1;
                        mBCount += 1;
                        if (isForwardDir) {
                            mByte[nozzleNum + m_offset_bytes] = 1;
                        } else {
                            mByte[nozzleNum + offset_bytes + m_offset_bytes] = 1;
                        }
                    }
                    if ((mByte_HT[i] & 0x40) == 0x40) {
                        nozzleNum = cnt * 2;
                        mCount += 1;
                        if (isForwardDir) {
                            mByte[nozzleNum + offset_bytes + m_offset_bytes] = 1;
                        } else {
                            mByte[nozzleNum + m_offset_bytes] = 1;
                        }
                    }
                    if ((yByte_HT[i] & 0x80) == 0x80) {
                        nozzleNum = cnt * 2 + 1;
                        yBCount += 1;
                        if (isForwardDir) {
                            yByte[nozzleNum + y_offset_bytes] = 1;
                        } else {
                            yByte[nozzleNum + offset_bytes] = 1;
                        }
                    }
                    if ((yByte_HT[i] & 0x40) == 0x40) {
                        nozzleNum = cnt * 2;
                        yCount += 1;
                        if (isForwardDir) {
                            yByte[nozzleNum + offset_bytes + y_offset_bytes] = 1;
                        } else {
                            yByte[nozzleNum] = 1;
                        }
                    }
                } else {
                    if ((cByte_HT[i] & 0x80) == 0x80) {
                        nozzleNum = cnt * 2;
                        cBCount += 1;
                        if (isForwardDir) {
                            cByte[nozzleNum + offset_bytes] = 1;
                        } else {
                            cByte[nozzleNum + y_offset_bytes] = 1;
                        }
                    }
                    if ((cByte_HT[i] & 0x40) == 0x40) {
                        nozzleNum = cnt * 2 + 1;
                        cCount += 1;
                        if (isForwardDir) {
                            cByte[nozzleNum] = 1;
                        } else {
                            cByte[nozzleNum + offset_bytes + y_offset_bytes] = 1;
                        }
                    }
                    if ((mByte_HT[i] & 0x80) == 0x80) {
                        nozzleNum = cnt * 2;
                        mBCount += 1;
                        if (isForwardDir) {
                            mByte[nozzleNum + offset_bytes + m_offset_bytes] = 1;
                        } else {
                            mByte[nozzleNum + m_offset_bytes] = 1;
                        }
                    }
                    if ((mByte_HT[i] & 0x40) == 0x40) {
                        nozzleNum = cnt * 2 + 1;
                        mCount += 1;
                        if (isForwardDir) {
                            mByte[nozzleNum + m_offset_bytes] = 1;
                        } else {
                            mByte[nozzleNum + offset_bytes + m_offset_bytes] = 1;
                        }
                    }
                    if ((yByte_HT[i] & 0x80) == 0x80) {
                        nozzleNum = cnt * 2;
                        yBCount += 1;
                        if (isForwardDir) {
                            yByte[nozzleNum + offset_bytes + y_offset_bytes] = 1;
                        } else {
                            yByte[nozzleNum] = 1;
                        }
                    }
                    if ((yByte_HT[i] & 0x40) == 0x40) {
                        nozzleNum = cnt * 2 + 1;
                        yCount += 1;
                        if (isForwardDir) {
                            yByte[nozzleNum + y_offset_bytes] = 1;
                        } else {
                            yByte[nozzleNum + offset_bytes] = 1;
                        }
                    }
                }
                ++cnt;
            }
//            Log.i("cByte.length:" + cByte.length);
//            Log.i("cByte:" + Arrays.toString(cByte));
        }

        // [5] 将CMY组合到字节流cmyBytes
        private void mergeCMYData() {
            int size = cByte.length / 8;
            byte[] bytesArr_c = new byte[size];
            byte[] bytesArr_m = new byte[size];
            byte[] bytesArr_y = new byte[size];

            for (int i = 0; i < size; i++) {
                for (int m = 0; m < 8; m++) {
                    bytesArr_c[i] += (cByte[i * 8 + m] << m);
                }
                for (int m = 0; m < 8; m++) {
                    bytesArr_m[i] += (mByte[i * 8 + m] << m);
                }
                for (int m = 0; m < 8; m++) {
                    bytesArr_y[i] += (yByte[i * 8 + m] << m);
                }
            }
            bytesArr_sum = new byte[size * 3];
            int size86 = size / 86;
            for (int i = 0; i < size86; i++) {
                for (int m = 0; m < 86; m++) {
                    bytesArr_sum[i * 86 * 3 + m] = bytesArr_y[i * 86 + m];
                }
                for (int m = 0; m < 86; m++) {
                    bytesArr_sum[i * 86 * 3 + 86 + m] = bytesArr_m[i * 86 + m];
                }
                for (int m = 0; m < 86; m++) {
                    bytesArr_sum[i * 86 * 3 + 86 + 86 + m] = bytesArr_c[i * 86 + m];
                }
            }
        }

        private void packbitsEncode() {
            try {
                imageData = PackBits.compress(bytesArr_sum);
//                Log.i("imageData_first:" + Arrays.toString(imageData_first));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        private void floyd_steinberg_mbpp(int singlePlane[], int width, int height, int destArray[]) {
            int[] initRow = new int[imgWidth];
            int[] errorRow0 = new int[imgWidth];
            int[] errorRow1 = new int[imgWidth];
            for (int i = 0; i < imgWidth; i++) {
                errorRow0[i] = 0;
                errorRow1[i] = 0;
                initRow[i] = 0;
            }

            int singlePixelError = 0;
            int reverseIndex = 0;

            int threshold, threshold1, threshold2;

            int r1, r2, r3;
            Random random1 = new Random();
            Random random2 = new Random();
            Random random3 = new Random();

            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    r1 = random1.nextInt(50);
                    r2 = random2.nextInt(50);
                    r3 = random3.nextInt(50);

                    threshold = r1 + (breakpoints[0] - 25);
                    threshold1 = r2 + (breakpoints[1] - 25);
                    threshold2 = r3 + (breakpoints[2] - 25);

                    if (/*y % 2 == 0*/true) {   //Left to Right
                        if (singlePlane[y * width + x] + errorRow0[x] < threshold) {
                            singlePixelError = (singlePlane[y * width + x] + errorRow0[x]);
                            destArray[y * width + x] = 0;
                        } else if (singlePlane[y * width + x] + errorRow0[x] < threshold1) {
                            singlePixelError = (singlePlane[y * width + x] + errorRow0[x]) - breakpoints[0];
                            destArray[y * width + x] = breakpoints[0];
                        } else if (singlePlane[y * width + x] + errorRow0[x] < threshold2) {
                            singlePixelError = (singlePlane[y * width + x] + errorRow0[x]) - breakpoints[1];
                            destArray[y * width + x] = breakpoints[1];
                        } else {
                            singlePixelError = (singlePlane[y * width + x] + errorRow0[x]) - breakpoints[2];
                            destArray[y * width + x] = breakpoints[2];
                        }
                        if (singlePixelError != 0)
                            diffuse(singlePixelError, x, false, errorRow0, errorRow1);
                    } else {    //Right to Left
                        reverseIndex = width - x - 1;
                        if (singlePlane[y * width + reverseIndex] + errorRow0[reverseIndex] < threshold) {
                            singlePixelError = (singlePlane[y * width + reverseIndex] + errorRow0[reverseIndex]);
                            destArray[y * width + reverseIndex] = 0;
                        } else if (singlePlane[y * width + reverseIndex] + errorRow0[reverseIndex] < threshold1) {
                            singlePixelError =
                                    (singlePlane[y * width + reverseIndex] + errorRow0[reverseIndex]) - breakpoints[0];
                            destArray[y * width + reverseIndex] = breakpoints[0];
                        } else if (singlePlane[y * width + reverseIndex] + errorRow0[reverseIndex] < threshold2) {
                            singlePixelError =
                                    (singlePlane[y * width + reverseIndex] + errorRow0[reverseIndex]) - breakpoints[1];
                            destArray[y * width + reverseIndex] = breakpoints[1];
                        } else {
                            singlePixelError =
                                    (singlePlane[y * width + reverseIndex] + errorRow0[reverseIndex]) - breakpoints[2];
                            destArray[y * width + reverseIndex] = breakpoints[2];
                        }
                        if (singlePixelError != 0)
                            diffuse(singlePixelError, reverseIndex, false, errorRow0, errorRow1);
                    }
                }
                System.arraycopy(errorRow1, 0, errorRow0, 0, imgWidth);
                System.arraycopy(initRow, 0, errorRow1, 0, imgWidth);
            }
        }

        private void ink_seperation_colormap(int cBitmap[], int mBitmap[], int yBitmap[],
                                             int width,
                                             int height, boolean isNewFormat) {
            int r, g, b;

            for (int y = 0; y < imgHeight; y++) {
                for (int x = 0; x < imgWidth; x++) {
                    int pixel = bitmap.getPixel(x, y);
                    r = Color.red(pixel);
                    g = Color.green(pixel);
                    b = Color.blue(pixel);

                    if (isNewFormat) {
                        int[] cmyVal = color_convert_with_tetrahedral_interpolation(r, g, b, colorMap[0]);

                        cBitmap[y * imgWidth + x] = (int) cmyVal[0];
                        mBitmap[y * imgWidth + x] = (int) cmyVal[1];
                        yBitmap[y * imgWidth + x] = (int) cmyVal[2];
                    } else {
                        cBitmap[y * imgWidth + x] = (int) (0xff - r);
                        mBitmap[y * imgWidth + x] = (int) (0xff - g);
                        yBitmap[y * imgWidth + x] = (int) (0xff - b);
                    }
                }
            }
        }

        private void diffuse(int error, int index, boolean isLtR, int errorRow0[], int errorRow1[]) {
            double[] kernel = new double[5];
            if (isLtR) {
                kernel[0] = 0;
                kernel[1] = 3 / 16.0;
                kernel[2] = 7 / 16.0;
                kernel[3] = 1 / 16.0;
                kernel[4] = 5 / 16.0;
            } else {
                kernel[0] = 7 / 16.0;
                kernel[1] = 1 / 16.0;
                kernel[2] = 0;
                kernel[3] = 3 / 16.0;
                kernel[4] = 5 / 16.0;
            }

            if (index > 0) {
                errorRow0[index - 1] += (int) ceil(error * kernel[0]);
                errorRow1[index - 1] += (int) ceil(error * kernel[1]);
            }
            if (index < errorRow0.length - 1) {
                errorRow0[index + 1] += (int) ceil(error * kernel[2]);
                errorRow1[index + 1] += (int) ceil(error * kernel[3]);
            }
            errorRow1[index] += (int) ceil(error * kernel[4]);
        }

        private int get_node_index_from_8bit_value(int value, int numberOfNodes) {
            return (value + 1) / (int) ceil(256 / (numberOfNodes - 1));
        }

        private int compute_distance_from_lowest_node(int value, int numberOfNodes) {
            int nodeIndex = get_node_index_from_8bit_value(value, numberOfNodes);
            int distancePerNode = (int) ceil(256 / (numberOfNodes - 1));
            int distanceFromLowestNode = value - (nodeIndex * distancePerNode);
            if (distanceFromLowestNode < 1) return 0;
            return distanceFromLowestNode;
        }

        private int determine_tetrahral_number(int r, int g, int b, int numberOfNodes) {
            r = compute_distance_from_lowest_node(r, numberOfNodes);
            g = compute_distance_from_lowest_node(g, numberOfNodes);
            b = compute_distance_from_lowest_node(b, numberOfNodes);
            if (g >= b && b >= r)
                return 1;
            if (b > r && r > g)
                return 2;
            if (b > g && g >= r)
                return 3;
            if (r >= g && g > b)
                return 4;
            if (g > r && r >= b)
                return 5;
            if (r >= b && b >= g)
                return 6;

            return -1;
        }

        private int get_colormap_array_index(int r, int g, int b, int colorIndex, int numberOfNodes) {
            int index = 3 * (r + numberOfNodes * g + numberOfNodes * numberOfNodes * b) + 1 + colorIndex;

            return index;
        }

        private boolean does_8bit_value_fall_on_node(int value, int numberOfNodes) {
            int divisor = (int) ceil(256 / (numberOfNodes - 1));
            if (value % divisor == 0 || value == 255)
                return true;
            return false;
        }

        private int[] get_nearest_neighbors(int r, int g, int b, int numberOfNodes) {
            int[] nearestNodes = new int[24];
            int rIndex = get_node_index_from_8bit_value(r, numberOfNodes), rIndexPlusOne = rIndex;
            int gIndex = get_node_index_from_8bit_value(g, numberOfNodes), gIndexPlusOne = gIndex;
            int bIndex = get_node_index_from_8bit_value(b, numberOfNodes), bIndexPlusOne = bIndex;

            if (!does_8bit_value_fall_on_node(r, numberOfNodes)) {
                rIndexPlusOne++;
            }

            if (!does_8bit_value_fall_on_node(g, numberOfNodes)) {
                gIndexPlusOne++;
            }

            if (!does_8bit_value_fall_on_node(b, numberOfNodes)) {
                bIndexPlusOne++;
            }

            for (int i = 0; i < 3; i++) {
                nearestNodes[0 + i] = colorMap[get_colormap_array_index(rIndex, gIndex, bIndex, i, numberOfNodes)];
                nearestNodes[1 * 3 + i] = colorMap[get_colormap_array_index(rIndexPlusOne, gIndex, bIndex, i, numberOfNodes)];
                nearestNodes[2 * 3 + i] = colorMap[get_colormap_array_index(rIndex, gIndexPlusOne, bIndex, i, numberOfNodes)];
                nearestNodes[3 * 3 + i] = colorMap[get_colormap_array_index(rIndex, gIndex, bIndexPlusOne, i, numberOfNodes)];
                nearestNodes[4 * 3 + i] = colorMap[get_colormap_array_index(rIndexPlusOne, gIndexPlusOne, bIndex, i,
                        numberOfNodes)];
                nearestNodes[5 * 3 + i] = colorMap[get_colormap_array_index(rIndexPlusOne, gIndex, bIndexPlusOne, i,
                        numberOfNodes)];
                nearestNodes[6 * 3 + i] = colorMap[get_colormap_array_index(rIndex, gIndexPlusOne, bIndexPlusOne, i,
                        numberOfNodes)];
                nearestNodes[7 * 3 + i] = colorMap[get_colormap_array_index(rIndexPlusOne, gIndexPlusOne, bIndexPlusOne, i,
                        numberOfNodes)];
            }
            return nearestNodes;
        }

        private int[] color_convert_with_tetrahedral_interpolation(int r, int g, int b, int numberOfNodes) {
            int[] interpolatedInkFill = new int[3];
            int tetNumber = determine_tetrahral_number(r, g, b, numberOfNodes);

            int[] nearestNodes = get_nearest_neighbors(r, g, b, numberOfNodes);
            if (r == 255 && g == 255 && b == 255) {
                interpolatedInkFill[0] = 0;
                interpolatedInkFill[1] = 0;
                interpolatedInkFill[2] = 0;
            }
            int divisor = (int) ceil(256 / (numberOfNodes - 1));
            double rr, gg, bb;
            rr = (double) (compute_distance_from_lowest_node(r, numberOfNodes)) / divisor;
            gg = (double) (compute_distance_from_lowest_node(g, numberOfNodes)) / divisor;
            bb = (double) (compute_distance_from_lowest_node(b, numberOfNodes)) / divisor;

            for (int i = 0; i < 3; i++) {
                switch (tetNumber) {
                    case 1:
                        interpolatedInkFill[i] = (int) ((1 - gg) * nearestNodes[i] + (gg - bb) * nearestNodes[2 * 3 + i] +
                                (bb - rr) * nearestNodes[6 * 3 + i] + rr * nearestNodes[7 * 3 + i]);
                        break;
                    case 2:
                        interpolatedInkFill[i] = (int) ((1 - bb) * nearestNodes[i] + (bb - rr) * nearestNodes[3 * 3 + i] +
                                (rr - gg) * nearestNodes[5 * 3 + i] + gg * nearestNodes[7 * 3 + i]);
                        break;
                    case 3:
                        interpolatedInkFill[i] = (int) ((1 - bb) * nearestNodes[i] + (bb - gg) * nearestNodes[3 * 3 + i] +
                                (gg - rr) * nearestNodes[6 * 3 + i] + rr * nearestNodes[7 * 3 + i]);
                        break;
                    case 4:
                        interpolatedInkFill[i] = (int) ((1 - rr) * nearestNodes[i] + (rr - gg) * nearestNodes[1 * 3 + i] +
                                (gg - bb) * nearestNodes[4 * 3 + i] + bb * nearestNodes[7 * 3 + i]);
                        break;
                    case 5:
                        interpolatedInkFill[i] = (int) ((1 - gg) * nearestNodes[i] + (gg - rr) * nearestNodes[2 * 3 + i] +
                                (rr - bb) * nearestNodes[4 * 3 + i] + bb * nearestNodes[7 * 3 + i]);
                        break;
                    case 6:
                        interpolatedInkFill[i] = (int) ((1 - rr) * nearestNodes[i] + (rr - bb) * nearestNodes[1 * 3 + i] +
                                (bb - gg) * nearestNodes[5 * 3 + i] + gg * nearestNodes[7 * 3 + i]);
                        break;
                }
            }
            return interpolatedInkFill;
        }

        int[] breakpoints = {0x40, 0x80, 0xff};
        int[] colorMap = {0x09,
                0xcb, 0xbc, 0xb6, 0xa7, 0xcf, 0xbb, 0x7f, 0xdf, 0xbc,
                0x61, 0xe3, 0xb4, 0x43, 0xe6, 0xae, 0x2a, 0xea, 0xaf,
                0x17, 0xec, 0xb5, 0x0a, 0xec, 0xbf, 0x00, 0xec, 0xc9,
                0xbc, 0x96, 0xc4, 0xaf, 0xa2, 0xc7, 0x93, 0xae, 0xd0,
                0x6c, 0xb6, 0xc3, 0x4d, 0xbd, 0xb4, 0x24, 0xd8, 0xbe,
                0x0e, 0xe2, 0xc6, 0x05, 0xe5, 0xd0, 0x00, 0xdf, 0xd5,
                0xb7, 0x6e, 0xcd, 0xa9, 0x79, 0xd2, 0x98, 0x88, 0xd4,
                0x77, 0x8e, 0xdf, 0x57, 0x98, 0xca, 0x2e, 0xb2, 0xdc,
                0x16, 0xc0, 0xde, 0x08, 0xc8, 0xe2, 0x00, 0xc9, 0xe2,
                0xb5, 0x4f, 0xd5, 0xa8, 0x57, 0xd9, 0x98, 0x61, 0xdc,
                0x7b, 0x6b, 0xe0, 0x5b, 0x76, 0xe6, 0x3a, 0x85, 0xeb,
                0x21, 0x93, 0xec, 0x0c, 0xa1, 0xed, 0x00, 0xaa, 0xec,
                0xb4, 0x31, 0xdb, 0xaa, 0x33, 0xde, 0x98, 0x3e, 0xe2,
                0x81, 0x47, 0xe5, 0x62, 0x54, 0xe7, 0x43, 0x58, 0xed,
                0x28, 0x68, 0xef, 0x11, 0x76, 0xf1, 0x00, 0x84, 0xf2,
                0xb1, 0x19, 0xde, 0xa9, 0x1b, 0xe2, 0x9a, 0x22, 0xe5,
                0x85, 0x29, 0xe8, 0x6c, 0x31, 0xeb, 0x44, 0x38, 0xed,
                0x2d, 0x41, 0xf0, 0x16, 0x4e, 0xf3, 0x00, 0x5e, 0xf5,
                0xac, 0x0a, 0xe2, 0xa7, 0x0a, 0xe5, 0x9a, 0x0e, 0xe8,
                0x88, 0x13, 0xeb, 0x73, 0x18, 0xed, 0x58, 0x1e, 0xef,
                0x2f, 0x24, 0xf1, 0x19, 0x2b, 0xf3, 0x00, 0x3b, 0xf6,
                0xab, 0x02, 0xe4, 0xa4, 0x00, 0xe7, 0x9b, 0x01, 0xe9,
                0x8b, 0x05, 0xec, 0x77, 0x08, 0xee, 0x61, 0x0a, 0xf0,
                0x44, 0x0d, 0xf2, 0x18, 0x12, 0xf3, 0x00, 0x19, 0xf6,
                0xa8, 0x00, 0xe7, 0xa3, 0x00, 0xe8, 0x9b, 0x00, 0xea,
                0x8f, 0x00, 0xec, 0x7d, 0x00, 0xef, 0x69, 0x00, 0xf1,
                0x52, 0x00, 0xf3, 0x30, 0x00, 0xf5, 0x00, 0x00, 0xf6,
                0xd0, 0xb6, 0x89, 0xa4, 0xc7, 0x93, 0x7f, 0xdc, 0xa2,
                0x61, 0xe1, 0x9e, 0x43, 0xe5, 0x9b, 0x2a, 0xe9, 0x9c,
                0x17, 0xec, 0xa4, 0x0a, 0xec, 0xae, 0x00, 0xec, 0xbc,
                0xc9, 0xa4, 0x9f, 0xac, 0xa6, 0xa0, 0x8f, 0xa7, 0xa4,
                0x6c, 0xaa, 0x9c, 0x4b, 0xb2, 0x9a, 0x2d, 0xbd, 0x9e,
                0x10, 0xde, 0xb3, 0x03, 0xe3, 0xb8, 0x00, 0xd9, 0xbd,
                0xc4, 0x74, 0xc0, 0xab, 0x72, 0xc0, 0x8e, 0x7c, 0xbd,
                0x72, 0x87, 0xaf, 0x54, 0x90, 0xa9, 0x35, 0x9c, 0xa8,
                0x1a, 0xb7, 0xbf, 0x06, 0xc8, 0xcb, 0x00, 0xc9, 0xcc,
                0xbd, 0x52, 0xcf, 0xab, 0x4a, 0xd6, 0x94, 0x56, 0xd3,
                0x76, 0x61, 0xcc, 0x5a, 0x68, 0xb5, 0x3e, 0x76, 0xb1,
                0x21, 0x81, 0xab, 0x0e, 0x9c, 0xc8, 0x00, 0xae, 0xd9,
                0xb7, 0x31, 0xd6, 0xaa, 0x28, 0xdf, 0x98, 0x31, 0xe1,
                0x7d, 0x3d, 0xe0, 0x5d, 0x48, 0xd8, 0x44, 0x51, 0xc6,
                0x29, 0x5c, 0xb0, 0x11, 0x6e, 0xba, 0x00, 0x88, 0xe0,
                0xb3, 0x19, 0xdc, 0xa7, 0x0f, 0xe4, 0x9a, 0x14, 0xe6,
                0x84, 0x1f, 0xe8, 0x69, 0x29, 0xe7, 0x45, 0x31, 0xe1,
                0x2d, 0x3c, 0xd4, 0x17, 0x4c, 0xd2, 0x00, 0x61, 0xe4,
                0xaf, 0x08, 0xe1, 0xa4, 0x00, 0xe5, 0x9a, 0x02, 0xe7,
                0x89, 0x07, 0xeb, 0x71, 0x10, 0xed, 0x55, 0x17, 0xeb,
                0x2e, 0x1e, 0xe2, 0x16, 0x2b, 0xe0, 0x00, 0x3d, 0xe8,
                0xac, 0x00, 0xe3, 0x9f, 0x00, 0xdd, 0x97, 0x00, 0xdf,
                0x8b, 0x00, 0xe5, 0x78, 0x01, 0xec, 0x60, 0x04, 0xef,
                0x43, 0x09, 0xec, 0x19, 0x0d, 0xe4, 0x00, 0x19, 0xe8,
                0xa8, 0x00, 0xe7, 0x9e, 0x00, 0xd5, 0x97, 0x00, 0xd7,
                0x8b, 0x00, 0xdb, 0x7b, 0x00, 0xe0, 0x67, 0x00, 0xe4,
                0x50, 0x00, 0xe3, 0x31, 0x00, 0xe4, 0x00, 0x00, 0xe0,
                0xd9, 0xb5, 0x44, 0xae, 0xc6, 0x45, 0x7c, 0xd1, 0x6e,
                0x62, 0xdc, 0x80, 0x46, 0xe2, 0x7e, 0x2d, 0xe7, 0x80,
                0x19, 0xea, 0x86, 0x0b, 0xec, 0x91, 0x00, 0xea, 0x9e,
                0xd4, 0x9c, 0x57, 0xb5, 0x9c, 0x66, 0x8a, 0xad, 0x6f,
                0x6f, 0xa8, 0x75, 0x4f, 0xb1, 0x76, 0x2c, 0xcd, 0x80,
                0x12, 0xde, 0x86, 0x03, 0xe3, 0x95, 0x00, 0xda, 0xa5,
                0xc6, 0x7f, 0x7b, 0xaf, 0x75, 0x88, 0x8e, 0x82, 0x84,
                0x76, 0x8a, 0x88, 0x57, 0x93, 0x84, 0x38, 0x9b, 0x84,
                0x1c, 0xa8, 0x88, 0x06, 0xc1, 0x9b, 0x00, 0xc1, 0xa2,
                0xc5, 0x52, 0xaa, 0xaf, 0x4f, 0xad, 0x91, 0x57, 0xa3,
                0x75, 0x61, 0x9f, 0x5c, 0x6d, 0x95, 0x3f, 0x77, 0x90,
                0x22, 0x84, 0x90, 0x0d, 0x9b, 0xa1, 0x00, 0xab, 0xb0,
                0xc0, 0x2e, 0xbf, 0xae, 0x2c, 0xc4, 0x97, 0x32, 0xbd,
                0x7c, 0x3e, 0xb7, 0x5d, 0x48, 0xaf, 0x46, 0x52, 0x9e,
                0x2a, 0x5f, 0x99, 0x10, 0x6f, 0x9b, 0x00, 0x8c, 0xbb,
                0xba, 0x17, 0xcf, 0xac, 0x0e, 0xd5, 0x99, 0x12, 0xcb,
                0x85, 0x1f, 0xca, 0x69, 0x2b, 0xc3, 0x47, 0x32, 0xb8,
                0x33, 0x3b, 0xa3, 0x18, 0x4a, 0xa1, 0x00, 0x67, 0xc0,
                0xb6, 0x04, 0xda, 0xa9, 0x00, 0xd9, 0x98, 0x00, 0xd2,
                0x89, 0x05, 0xd6, 0x72, 0x11, 0xd4, 0x56, 0x1b, 0xcc,
                0x30, 0x20, 0xc0, 0x1a, 0x2b, 0xb9, 0x00, 0x42, 0xc7,
                0xb1, 0x00, 0xe0, 0xa1, 0x00, 0xd4, 0x94, 0x00, 0xca,
                0x89, 0x00, 0xcf, 0x78, 0x00, 0xd8, 0x5f, 0x05, 0xd9,
                0x42, 0x0b, 0xd1, 0x19, 0x10, 0xc8, 0x00, 0x1f, 0xcb,
                0xaf, 0x00, 0xe1, 0xa0, 0x00, 0xcf, 0x94, 0x00, 0xc4,
                0x89, 0x00, 0xc8, 0x7a, 0x00, 0xce, 0x66, 0x00, 0xd2,
                0x4e, 0x00, 0xd1, 0x2f, 0x00, 0xd0, 0x00, 0x00, 0xca,
                0xe3, 0xa2, 0x1e, 0xbf, 0xb6, 0x02, 0x8e, 0xce, 0x15,
                0x62, 0xd3, 0x58, 0x47, 0xdd, 0x64, 0x2f, 0xe3, 0x63,
                0x1c, 0xe7, 0x66, 0x0d, 0xea, 0x70, 0x00, 0xe9, 0x7b,
                0xe1, 0x8b, 0x19, 0xc3, 0x8d, 0x2d, 0x96, 0xad, 0x2a,
                0x6b, 0xbb, 0x3e, 0x49, 0xc3, 0x4b, 0x2d, 0xd0, 0x51,
                0x15, 0xdc, 0x57, 0x04, 0xe1, 0x6b, 0x00, 0xd9, 0x87,
                0xd5, 0x7b, 0x35, 0xb9, 0x77, 0x50, 0x9a, 0x7e, 0x50,
                0x79, 0x8a, 0x5a, 0x57, 0x8f, 0x5b, 0x3a, 0x9b, 0x5e,
                0x1c, 0xb6, 0x66, 0x07, 0xc0, 0x73, 0x00, 0xc2, 0x8c,
                0xc3, 0x60, 0x5c, 0xb3, 0x54, 0x70, 0x95, 0x59, 0x71,
                0x74, 0x66, 0x6b, 0x5e, 0x70, 0x70, 0x42, 0x79, 0x6d,
                0x25, 0x85, 0x6c, 0x0a, 0x95, 0x72, 0x00, 0xa7, 0x7f,
                0xc6, 0x33, 0x90, 0xb3, 0x31, 0x94, 0x9a, 0x37, 0x95,
                0x79, 0x3e, 0x89, 0x5d, 0x48, 0x85, 0x47, 0x56, 0x7c,
                0x2b, 0x60, 0x79, 0x0f, 0x70, 0x7a, 0x00, 0x8b, 0x8f,
                0xc0, 0x10, 0xbe, 0xb3, 0x16, 0xb1, 0x9c, 0x1b, 0xaa,
                0x80, 0x1f, 0xa0, 0x66, 0x2b, 0x9b, 0x48, 0x34, 0x94,
                0x33, 0x3e, 0x85, 0x17, 0x4b, 0x82, 0x00, 0x64, 0x8c,
                0xc5, 0x00, 0xca, 0xaf, 0x03, 0xbf, 0x9d, 0x03, 0xb8,
                0x85, 0x06, 0xb0, 0x71, 0x11, 0xaf, 0x55, 0x1c, 0xaa,
                0x33, 0x22, 0x9e, 0x1d, 0x2a, 0x91, 0x00, 0x3f, 0x95,
                0xbc, 0x00, 0xd6, 0xa9, 0x00, 0xc5, 0x9a, 0x00, 0xb9,
                0x86, 0x00, 0xb4, 0x77, 0x01, 0xb9, 0x5f, 0x07, 0xba,
                0x42, 0x0d, 0xb2, 0x1b, 0x11, 0xa8, 0x00, 0x22, 0xab,
                0xbb, 0x00, 0xd8, 0xa7, 0x00, 0xc4, 0x98, 0x00, 0xb8,
                0x87, 0x00, 0xb3, 0x78, 0x00, 0xb8, 0x65, 0x00, 0xbc,
                0x4d, 0x00, 0xb9, 0x2f, 0x00, 0xb7, 0x00, 0x00, 0xb1,
                0xeb, 0x98, 0x0a, 0xd3, 0xa2, 0x00, 0xa8, 0xba, 0x00,
                0x74, 0xd0, 0x08, 0x48, 0xd5, 0x41, 0x31, 0xde, 0x4b,
                0x1d, 0xe3, 0x4c, 0x0e, 0xe7, 0x51, 0x00, 0xe6, 0x59,
                0xe3, 0x82, 0x00, 0xd5, 0x88, 0x05, 0xaa, 0xa5, 0x01,
                0x7b, 0xb9, 0x04, 0x4b, 0xc7, 0x16, 0x2b, 0xd0, 0x22,
                0x17, 0xda, 0x2c, 0x06, 0xdd, 0x41, 0x00, 0xd8, 0x68,
                0xd9, 0x6e, 0x06, 0xc5, 0x72, 0x1f, 0xa7, 0x7a, 0x19,
                0x7f, 0x94, 0x18, 0x55, 0xa1, 0x23, 0x34, 0xad, 0x2d,
                0x1c, 0xba, 0x37, 0x07, 0xc2, 0x4b, 0x00, 0xc1, 0x70,
                0xcc, 0x5d, 0x27, 0xb7, 0x59, 0x3d, 0x9d, 0x5d, 0x40,
                0x80, 0x65, 0x3c, 0x60, 0x71, 0x44, 0x42, 0x78, 0x45,
                0x26, 0x84, 0x46, 0x09, 0x95, 0x4d, 0x00, 0xa7, 0x67,
                0xbf, 0x45, 0x43, 0xb4, 0x36, 0x57, 0x9d, 0x39, 0x60,
                0x7b, 0x40, 0x5b, 0x5d, 0x4c, 0x55, 0x47, 0x58, 0x57,
                0x2e, 0x61, 0x55, 0x0f, 0x70, 0x54, 0x00, 0x87, 0x5e,
                0xc6, 0x1b, 0x83, 0xba, 0x1a, 0x83, 0xa1, 0x21, 0x83,
                0x83, 0x23, 0x7d, 0x62, 0x2b, 0x71, 0x47, 0x35, 0x6d,
                0x31, 0x41, 0x64, 0x17, 0x4d, 0x62, 0x00, 0x67, 0x70,
                0xcd, 0x01, 0xaa, 0xb6, 0x09, 0xa5, 0xa1, 0x0c, 0x9c,
                0x89, 0x0b, 0x94, 0x6d, 0x10, 0x8b, 0x53, 0x1c, 0x87,
                0x33, 0x23, 0x7d, 0x1e, 0x2b, 0x71, 0x00, 0x43, 0x7c,
                0xca, 0x00, 0xbd, 0xb3, 0x00, 0xb0, 0x9f, 0x00, 0xa4,
                0x8a, 0x00, 0x9c, 0x74, 0x00, 0x9a, 0x5e, 0x06, 0x9a,
                0x41, 0x0e, 0x93, 0x1b, 0x11, 0x8a, 0x00, 0x23, 0x8c,
                0xc6, 0x00, 0xc7, 0xb0, 0x00, 0xb5, 0x9d, 0x00, 0xa7,
                0x8a, 0x00, 0xa0, 0x76, 0x00, 0x9d, 0x64, 0x00, 0xa0,
                0x4c, 0x00, 0x9f, 0x2e, 0x00, 0x9c, 0x00, 0x00, 0x95,
                0xec, 0x8c, 0x00, 0xe0, 0x95, 0x00, 0xbf, 0xae, 0x00,
                0x94, 0xbd, 0x00, 0x5e, 0xcf, 0x00, 0x31, 0xd7, 0x2c,
                0x1d, 0xdf, 0x34, 0x0f, 0xe3, 0x39, 0x00, 0xe2, 0x3e,
                0xdf, 0x81, 0x00, 0xd7, 0x84, 0x00, 0xb7, 0x9c, 0x00,
                0x94, 0xae, 0x00, 0x66, 0xba, 0x00, 0x35, 0xca, 0x01,
                0x18, 0xd4, 0x06, 0x07, 0xd8, 0x21, 0x00, 0xd5, 0x4b,
                0xd4, 0x71, 0x00, 0xcd, 0x6c, 0x00, 0xb4, 0x78, 0x00,
                0x91, 0x91, 0x00, 0x68, 0xa2, 0x00, 0x3c, 0xaf, 0x03,
                0x1c, 0xbc, 0x09, 0x06, 0xc3, 0x25, 0x00, 0xbf, 0x53,
                0xcd, 0x5c, 0x05, 0xbe, 0x59, 0x13, 0xaa, 0x5a, 0x14,
                0x8c, 0x64, 0x0c, 0x66, 0x7c, 0x0c, 0x41, 0x8a, 0x11,
                0x20, 0x98, 0x1d, 0x0c, 0xa1, 0x31, 0x00, 0xa8, 0x50,
                0xc4, 0x45, 0x19, 0xb2, 0x40, 0x2c, 0x9d, 0x40, 0x31,
                0x84, 0x45, 0x2e, 0x66, 0x4d, 0x29, 0x4a, 0x5a, 0x31,
                0x2f, 0x63, 0x31, 0x12, 0x74, 0x35, 0x00, 0x8d, 0x4d,
                0xbb, 0x2c, 0x2b, 0xb7, 0x1c, 0x42, 0xa2, 0x1e, 0x4b,
                0x86, 0x23, 0x4b, 0x64, 0x2b, 0x46, 0x46, 0x39, 0x40,
                0x32, 0x43, 0x41, 0x18, 0x4f, 0x3f, 0x00, 0x68, 0x44,
                0xc7, 0x08, 0x79, 0xbd, 0x08, 0x77, 0xa7, 0x0d, 0x73,
                0x8e, 0x10, 0x6f, 0x70, 0x13, 0x67, 0x4e, 0x1a, 0x5c,
                0x31, 0x23, 0x57, 0x1c, 0x2e, 0x4e, 0x00, 0x46, 0x58,
                0xd0, 0x00, 0x9a, 0xba, 0x00, 0x91, 0xa5, 0x02, 0x87,
                0x90, 0x01, 0x81, 0x77, 0x01, 0x7b, 0x5c, 0x05, 0x77,
                0x3f, 0x0d, 0x71, 0x1d, 0x11, 0x67, 0x00, 0x1e, 0x63,
                0xcf, 0x00, 0xac, 0xb8, 0x00, 0x9e, 0xa4, 0x00, 0x92,
                0x8e, 0x00, 0x8a, 0x78, 0x00, 0x84, 0x61, 0x00, 0x81,
                0x4b, 0x00, 0x81, 0x2c, 0x00, 0x7d, 0x00, 0x00, 0x77,
                0xef, 0x85, 0x00, 0xe6, 0x90, 0x02, 0xca, 0xa8, 0x00,
                0xab, 0xb6, 0x00, 0x82, 0xbf, 0x00, 0x4d, 0xcc, 0x00,
                0x1d, 0xd9, 0x1a, 0x0e, 0xdf, 0x22, 0x00, 0xdf, 0x28,
                0xde, 0x7f, 0x00, 0xd7, 0x81, 0x00, 0xbf, 0x95, 0x00,
                0xa3, 0xa6, 0x00, 0x82, 0xb2, 0x00, 0x57, 0xbb, 0x00,
                0x27, 0xc7, 0x00, 0x07, 0xd1, 0x09, 0x00, 0xd0, 0x36,
                0xd2, 0x72, 0x00, 0xcc, 0x6e, 0x00, 0xb8, 0x76, 0x00,
                0x9d, 0x8b, 0x00, 0x7d, 0x9b, 0x00, 0x58, 0xa5, 0x00,
                0x2d, 0xb1, 0x00, 0x06, 0xbf, 0x09, 0x00, 0xbd, 0x3e,
                0xc7, 0x63, 0x00, 0xc3, 0x5b, 0x00, 0xb2, 0x5c, 0x00,
                0x96, 0x63, 0x00, 0x76, 0x7b, 0x00, 0x52, 0x8b, 0x00,
                0x29, 0x99, 0x01, 0x06, 0xa8, 0x11, 0x00, 0xa7, 0x3c,
                0xc2, 0x4c, 0x02, 0xb8, 0x45, 0x0b, 0xa9, 0x43, 0x0c,
                0x91, 0x47, 0x0a, 0x73, 0x4e, 0x05, 0x4f, 0x67, 0x05,
                0x2b, 0x77, 0x08, 0x0e, 0x82, 0x18, 0x00, 0x8e, 0x3a,
                0xbc, 0x34, 0x10, 0xae, 0x2a, 0x1e, 0x9c, 0x29, 0x23,
                0x87, 0x2d, 0x22, 0x6d, 0x33, 0x1f, 0x51, 0x39, 0x19,
                0x34, 0x44, 0x1d, 0x19, 0x53, 0x21, 0x00, 0x6e, 0x35,
                0xb8, 0x19, 0x18, 0xb6, 0x07, 0x33, 0xa5, 0x07, 0x39,
                0x8d, 0x0d, 0x39, 0x72, 0x13, 0x38, 0x50, 0x1a, 0x34,
                0x30, 0x27, 0x2b, 0x1c, 0x30, 0x2d, 0x00, 0x47, 0x2f,
                0xcc, 0x02, 0x69, 0xba, 0x00, 0x61, 0xa8, 0x00, 0x5b,
                0x94, 0x01, 0x58, 0x7b, 0x03, 0x55, 0x5e, 0x05, 0x51,
                0x3c, 0x0b, 0x49, 0x1c, 0x12, 0x42, 0x00, 0x22, 0x44,
                0xd1, 0x00, 0x85, 0xbd, 0x00, 0x7c, 0xaa, 0x00, 0x72,
                0x95, 0x00, 0x6c, 0x7d, 0x00, 0x66, 0x63, 0x00, 0x61,
                0x48, 0x00, 0x5f, 0x2b, 0x00, 0x5b, 0x00, 0x00, 0x56,
                0xf5, 0x7f, 0x00, 0xe9, 0x8c, 0x03, 0xd2, 0xa2, 0x00,
                0xbb, 0xb0, 0x00, 0x9b, 0xba, 0x00, 0x74, 0xc1, 0x00,
                0x42, 0xca, 0x00, 0x0d, 0xda, 0x0b, 0x00, 0xdd, 0x13,
                0xe1, 0x7b, 0x00, 0xd7, 0x7f, 0x00, 0xc3, 0x8f, 0x00,
                0xab, 0xa0, 0x00, 0x92, 0xaa, 0x00, 0x70, 0xb3, 0x00,
                0x46, 0xb9, 0x00, 0x16, 0xc6, 0x00, 0x00, 0xcc, 0x25,
                0xd5, 0x73, 0x00, 0xcb, 0x6f, 0x00, 0xb9, 0x72, 0x00,
                0xa2, 0x85, 0x00, 0x89, 0x95, 0x00, 0x69, 0x9f, 0x00,
                0x42, 0xa8, 0x00, 0x11, 0xb7, 0x00, 0x00, 0xba, 0x2d,
                0xc8, 0x66, 0x00, 0xc2, 0x61, 0x00, 0xb2, 0x60, 0x00,
                0x9d, 0x61, 0x00, 0x82, 0x78, 0x00, 0x63, 0x88, 0x00,
                0x3e, 0x94, 0x00, 0x0d, 0xa3, 0x02, 0x00, 0xa5, 0x2e,
                0xbd, 0x56, 0x00, 0xb9, 0x4e, 0x00, 0xad, 0x4e, 0x00,
                0x9a, 0x4e, 0x00, 0x81, 0x4f, 0x00, 0x5f, 0x69, 0x00,
                0x3c, 0x7a, 0x00, 0x0c, 0x87, 0x03, 0x00, 0x8d, 0x2c,
                0xb7, 0x40, 0x00, 0xaf, 0x36, 0x06, 0xa3, 0x35, 0x05,
                0x92, 0x38, 0x04, 0x7b, 0x3b, 0x04, 0x62, 0x3c, 0x02,
                0x3b, 0x55, 0x02, 0x11, 0x63, 0x04, 0x00, 0x70, 0x27,
                0xb6, 0x26, 0x05, 0xa9, 0x1a, 0x11, 0x9a, 0x1b, 0x13,
                0x89, 0x1d, 0x14, 0x73, 0x20, 0x14, 0x5a, 0x24, 0x13,
                0x3e, 0x27, 0x0e, 0x1d, 0x30, 0x0c, 0x00, 0x4d, 0x22,
                0xb5, 0x0b, 0x0b, 0xad, 0x02, 0x23, 0x9f, 0x03, 0x23,
                0x8c, 0x03, 0x23, 0x76, 0x04, 0x24, 0x5e, 0x06, 0x24,
                0x3d, 0x0a, 0x22, 0x19, 0x14, 0x17, 0x00, 0x23, 0x1b,
                0xca, 0x00, 0x4e, 0xb9, 0x00, 0x4b, 0xa9, 0x00, 0x44,
                0x96, 0x00, 0x41, 0x80, 0x00, 0x3f, 0x66, 0x00, 0x3c,
                0x47, 0x00, 0x39, 0x28, 0x00, 0x35, 0x00, 0x00, 0x31,
                0xf6, 0x7d, 0x00, 0xe5, 0x8a, 0x00, 0xd4, 0xa0, 0x00,
                0xbf, 0xae, 0x00, 0xa7, 0xb7, 0x00, 0x87, 0xbe, 0x00,
                0x61, 0xc3, 0x00, 0x34, 0xcb, 0x00, 0x00, 0xdb, 0x00,
                0xea, 0x76, 0x00, 0xd8, 0x74, 0x00, 0xc4, 0x89, 0x00,
                0xb0, 0x9b, 0x00, 0x9c, 0xa6, 0x00, 0x7e, 0xaf, 0x00,
                0x59, 0xb5, 0x00, 0x2c, 0xbe, 0x00, 0x00, 0xc5, 0x00,
                0xdb, 0x71, 0x00, 0xcd, 0x6f, 0x00, 0xc0, 0x6a, 0x00,
                0xa8, 0x83, 0x00, 0x92, 0x93, 0x00, 0x76, 0x9e, 0x00,
                0x53, 0xa6, 0x00, 0x26, 0xb0, 0x00, 0x00, 0xb2, 0x00,
                0xcb, 0x68, 0x00, 0xc4, 0x66, 0x00, 0xb8, 0x63, 0x00,
                0xaa, 0x5f, 0x00, 0x8d, 0x78, 0x00, 0x70, 0x8a, 0x00,
                0x4f, 0x94, 0x00, 0x22, 0x9f, 0x00, 0x00, 0x9d, 0x00,
                0xb9, 0x5a, 0x00, 0xb8, 0x5a, 0x00, 0xb0, 0x58, 0x00,
                0xa3, 0x54, 0x00, 0x93, 0x4f, 0x00, 0x6f, 0x6c, 0x00,
                0x4d, 0x7d, 0x00, 0x21, 0x89, 0x00, 0x00, 0x86, 0x00,
                0xac, 0x46, 0x00, 0xae, 0x49, 0x00, 0xa6, 0x48, 0x00,
                0x9a, 0x46, 0x00, 0x8a, 0x44, 0x00, 0x76, 0x3d, 0x00,
                0x4c, 0x5b, 0x00, 0x21, 0x6c, 0x00, 0x00, 0x6d, 0x00,
                0xaa, 0x33, 0x00, 0xa7, 0x34, 0x00, 0x9c, 0x32, 0x00,
                0x8f, 0x31, 0x00, 0x80, 0x31, 0x00, 0x6c, 0x2f, 0x00,
                0x54, 0x29, 0x00, 0x24, 0x46, 0x00, 0x00, 0x4f, 0x00,
                0xaf, 0x1c, 0x00, 0xa5, 0x1d, 0x00, 0x98, 0x1c, 0x00,
                0x89, 0x1b, 0x00, 0x78, 0x1a, 0x00, 0x64, 0x19, 0x00,
                0x4c, 0x17, 0x00, 0x2d, 0x13, 0x00, 0x00, 0x2b, 0x00,
                0xb3, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x96, 0x00, 0x00,
                0x87, 0x00, 0x00, 0x74, 0x00, 0x00, 0x5e, 0x00, 0x00,
                0x44, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00
        };
    }
}
